package com.yunke.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yunke.entity.YunkeContactApply;
import com.yunke.mapper.YunkeContactApplyMapper;
import com.yunke.service.YunkeContactApplyService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 联系方式申请服务实现类
 * 
 * @author yunke
 * @since 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class YunkeContactApplyServiceImpl extends ServiceImpl<YunkeContactApplyMapper, YunkeContactApply> 
        implements YunkeContactApplyService {

    private final YunkeContactApplyMapper contactApplyMapper;
    
    // 申请状态常量
    private static final int STATUS_PENDING = 0;    // 待处理
    private static final int STATUS_APPROVED = 1;   // 已同意
    private static final int STATUS_REJECTED = 2;   // 已拒绝
    private static final int STATUS_EXPIRED = 3;    // 已过期
    
    // 每日申请限制
    private static final int DAILY_APPLY_LIMIT = 10;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submitApply(YunkeContactApply apply) {
        try {
            // 验证申请参数
            if (apply.getApplyUserId() == null || apply.getTargetUserId() == null) {
                throw new RuntimeException("申请用户或目标用户不能为空");
            }
            
            if (apply.getApplyUserId().equals(apply.getTargetUserId())) {
                throw new RuntimeException("不能向自己申请联系方式");
            }

            // 检查是否已存在申请
            YunkeContactApply existingApply = contactApplyMapper.selectExistingApply(
                    apply.getApplyUserId(), apply.getTargetUserId(), apply.getApplyType());
            if (existingApply != null && existingApply.getApplyStatus() == STATUS_PENDING) {
                throw new RuntimeException("已存在待处理的申请，请勿重复申请");
            }

            // 检查每日申请限制
            long todayCount = contactApplyMapper.countTodayApplies(apply.getApplyUserId());
            if (todayCount >= DAILY_APPLY_LIMIT) {
                throw new RuntimeException("今日申请次数已达上限");
            }

            // 检查申请权限
            if (!checkApplyPermission(apply.getApplyUserId(), apply.getTargetUserId())) {
                throw new RuntimeException("无权限申请此用户的联系方式");
            }

            // 设置默认值
            apply.setApplyStatus(STATUS_PENDING);
            apply.setIsRead(false);
            apply.setStatus(0);
            
            // 设置过期时间（7天后）
            long expireTime = System.currentTimeMillis() + 7 * 24 * 60 * 60 * 1000L;
            apply.setExpireTime(expireTime);
            
            apply.setCreateTime(System.currentTimeMillis());
            apply.setUpdateTime(System.currentTimeMillis());

            return this.save(apply);
            
        } catch (Exception e) {
            log.error("提交申请失败", e);
            throw new RuntimeException("提交申请失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean approveApply(Long id, Long userId) {
        try {
            YunkeContactApply apply = this.getById(id);
            if (apply == null || apply.getStatus() == 1) {
                throw new RuntimeException("申请不存在");
            }

            // 检查权限（只有目标用户才能同意申请）
            if (!apply.getTargetUserId().equals(userId)) {
                throw new RuntimeException("无权限处理此申请");
            }

            if (apply.getApplyStatus() != STATUS_PENDING) {
                throw new RuntimeException("申请状态不正确，无法处理");
            }

            // 检查是否过期
            if (System.currentTimeMillis() > apply.getExpireTime()) {
                throw new RuntimeException("申请已过期");
            }

            // 更新申请状态
            long currentTime = System.currentTimeMillis();
            int result = contactApplyMapper.updateApplyStatus(id, STATUS_APPROVED, currentTime, null);
            
            if (result > 0) {
                // TODO: 获取目标用户的联系方式信息并更新到申请记录
                // contactApplyMapper.updateContactInfo(id, contactInfo);
                
                // TODO: 发送通知给申请用户
                return true;
            }
            
            return false;
            
        } catch (Exception e) {
            log.error("同意申请失败", e);
            throw new RuntimeException("同意申请失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean rejectApply(Long id, Long userId, String rejectReason) {
        try {
            YunkeContactApply apply = this.getById(id);
            if (apply == null || apply.getStatus() == 1) {
                throw new RuntimeException("申请不存在");
            }

            // 检查权限（只有目标用户才能拒绝申请）
            if (!apply.getTargetUserId().equals(userId)) {
                throw new RuntimeException("无权限处理此申请");
            }

            if (apply.getApplyStatus() != STATUS_PENDING) {
                throw new RuntimeException("申请状态不正确，无法处理");
            }

            // 更新申请状态
            long currentTime = System.currentTimeMillis();
            int result = contactApplyMapper.updateApplyStatus(id, STATUS_REJECTED, currentTime, rejectReason);
            
            if (result > 0) {
                // TODO: 发送通知给申请用户
                return true;
            }
            
            return false;
            
        } catch (Exception e) {
            log.error("拒绝申请失败", e);
            throw new RuntimeException("拒绝申请失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelApply(Long id, Long userId) {
        try {
            YunkeContactApply apply = this.getById(id);
            if (apply == null || apply.getStatus() == 1) {
                throw new RuntimeException("申请不存在");
            }

            // 检查权限（只有申请用户才能取消申请）
            if (!apply.getApplyUserId().equals(userId)) {
                throw new RuntimeException("无权限取消此申请");
            }

            if (apply.getApplyStatus() != STATUS_PENDING) {
                throw new RuntimeException("申请状态不正确，无法取消");
            }

            // 删除申请
            apply.setStatus(1);
            apply.setUpdateTime(System.currentTimeMillis());
            return this.updateById(apply);
            
        } catch (Exception e) {
            log.error("取消申请失败", e);
            throw new RuntimeException("取消申请失败：" + e.getMessage());
        }
    }

    @Override
    public IPage<YunkeContactApply> getApplyPage(Integer current, Integer size, Long applyUserId, 
                                                Long targetUserId, Integer applyStatus) {
        Page<YunkeContactApply> page = new Page<>(current, size);
        return contactApplyMapper.selectApplyPage(page, applyUserId, targetUserId, applyStatus);
    }

    @Override
    public YunkeContactApply getApplyById(Long id) {
        LambdaQueryWrapper<YunkeContactApply> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(YunkeContactApply::getId, id)
               .eq(YunkeContactApply::getStatus, 0);
        return this.getOne(wrapper);
    }

    @Override
    public long getUnreadCount(Long userId) {
        return contactApplyMapper.countUnreadApplies(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean markAsRead(Long id) {
        return contactApplyMapper.markAsRead(id) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean markAllAsRead(Long userId) {
        return contactApplyMapper.markAllAsRead(userId) > 0;
    }

    @Override
    public Map<String, Object> getApplyStatistics() {
        List<Map<String, Object>> statistics = contactApplyMapper.getApplyStatistics();
        
        Map<String, Object> result = new HashMap<>();
        result.put("totalApplies", 0);
        result.put("pendingApplies", 0);
        result.put("approvedApplies", 0);
        result.put("rejectedApplies", 0);
        
        for (Map<String, Object> stat : statistics) {
            Integer status = (Integer) stat.get("apply_status");
            Long count = (Long) stat.get("count");
            
            result.put("totalApplies", (Long) result.get("totalApplies") + count);
            
            if (status == STATUS_PENDING) {
                result.put("pendingApplies", count);
            } else if (status == STATUS_APPROVED) {
                result.put("approvedApplies", count);
            } else if (status == STATUS_REJECTED) {
                result.put("rejectedApplies", count);
            }
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean forceApproveApply(Long id) {
        try {
            YunkeContactApply apply = this.getById(id);
            if (apply == null || apply.getStatus() == 1) {
                throw new RuntimeException("申请不存在");
            }

            long currentTime = System.currentTimeMillis();
            return contactApplyMapper.updateApplyStatus(id, STATUS_APPROVED, currentTime, "管理员强制同意") > 0;
            
        } catch (Exception e) {
            log.error("强制同意申请失败", e);
            throw new RuntimeException("强制同意申请失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean forceRejectApply(Long id, String reason) {
        try {
            YunkeContactApply apply = this.getById(id);
            if (apply == null || apply.getStatus() == 1) {
                throw new RuntimeException("申请不存在");
            }

            long currentTime = System.currentTimeMillis();
            return contactApplyMapper.updateApplyStatus(id, STATUS_REJECTED, currentTime, "管理员强制拒绝：" + reason) > 0;
            
        } catch (Exception e) {
            log.error("强制拒绝申请失败", e);
            throw new RuntimeException("强制拒绝申请失败：" + e.getMessage());
        }
    }

    @Override
    public boolean checkApplyPermission(Long applyUserId, Long targetUserId) {
        // TODO: 实现申请权限检查逻辑
        // 例如：检查是否被拉黑、是否设置了隐私保护等
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cleanExpiredApplies() {
        try {
            List<YunkeContactApply> expiredApplies = contactApplyMapper.selectExpiredApplies();
            if (!expiredApplies.isEmpty()) {
                List<Long> expiredIds = expiredApplies.stream()
                        .map(YunkeContactApply::getId)
                        .toList();
                
                return contactApplyMapper.batchUpdateExpiredApplies(expiredIds) > 0;
            }
            return true;
            
        } catch (Exception e) {
            log.error("清理过期申请失败", e);
            return false;
        }
    }
} 